package cn.lsc.service.impl;

import cn.lsc.doc.courseDoc;
import cn.lsc.domain.*;
import cn.lsc.dto.CourseDto;
import cn.lsc.enums.GlobaEnums;
import cn.lsc.feign.MediaFeignService;
import cn.lsc.feign.searchFeignService;
import cn.lsc.mapper.CourseMapper;
import cn.lsc.result.JSONResult;
import cn.lsc.service.*;
import cn.lsc.util.AssertUtil;
import cn.lsc.vo.CourseInfoVo;
import cn.lsc.web.controller.CourseTeacherController;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lsc
 * @since 2022-09-02
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ITeacherService teacherService;

    @Autowired
    private ICourseResourceService courseResourceService;

    @Autowired
    private ICourseDetailService courseDetailService;

    @Autowired
    private ICourseMarketService courseMarketService;

    @Autowired
    private ICourseSummaryService courseSummaryService;

    @Autowired
    private ICourseTeacherService courseTeacherService;

    @Autowired
    private ICourseTypeService courseTypeService;

    @Autowired
    private CourseMapper courseMapper;

    @Autowired
    private searchFeignService searchFeignService;

    @Autowired
    private ICourseChapterService iCourseChapterService;

    @Autowired
    private MediaFeignService mediaFeignService;

    @Autowired
    private ICourseUserLearnService iCourseUserLearnService;
    @Override
    public void save(CourseDto courseDto) {

        Course course = courseDto.getCourse();
        CourseResource courseResource = courseDto.getCourseResource();
        CourseDetail courseDetail = courseDto.getCourseDetail();
        CourseMarket courseMarket = courseDto.getCourseMarket();
        List<Long> teacherIds = courseDto.getTeacherIds();
        // 1.参数校验，使用JSR303进行校验
        // 2.判断课程是否存在，如果存在不允许添加，抛出异常
        isCourseExisted(course);
        // 3.保存课程 方法传递对象是引用传递，不是值传递，那么引用传递意味着，你这个对象共享地址，那么下面给这个对象设定了id，那么上面也有
        saveCourse(course, teacherIds);
        // 4.保存资源表
        saveCourseResourse(course, courseResource);
        // 5.保存详情
        saveCourseDetail(course, courseDetail);
        // 6.保存课程营销
        saveCourseMarket(course, courseMarket);
        // 7.初始化课程汇总
        initCourseSummary(course);
        // 8.保存课程老师中间表
        saveCourseTeacher(course, teacherIds);
        // 9.给课程对应类型数量+1
        courseTypeService.updateTotalCountById(course.getCourseTypeId());
    }



    private void saveCourseTeacher(Course course, List<Long> teacherIds) {
        //teacherIds.forEach(id->{
        //    CourseTeacher courseTeacher = new CourseTeacher();
        //    courseTeacher.setCourseId(course.getId());
        //    courseTeacher.setTeacherId(id);
        //    courseTeacherService.insert(courseTeacher);
        //});
        courseMapper.insertCourseTeacher(course.getId(), teacherIds);
    }

    private void initCourseSummary(Course course) {
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);
    }

    private void saveCourseMarket(Course course, CourseMarket courseMarket) {
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);
    }

    private void saveCourseDetail(Course course, CourseDetail courseDetail) {
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);
    }

    private void saveCourseResourse(Course course, CourseResource courseResource) {
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);
    }

    private void saveCourse(Course course, List<Long> teacherIds) {
        course.setStatus(Course.STATUS_OFFLINE);
        // @TODO 以后做完登录之后过来获取当前登员工
        course.setLoginId(6L);
        course.setLoginUserName("lsc.cn");
        course.setChapterCount(Course.INIT_CHAPTER_COUNT);

        List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);
        //StringBuilder sbr = new StringBuilder();
        //teachers.forEach(e->{
        //    sbr.append(e.getName()).append(",");
        //});
        // map：映射操作，拿到每个你指定的字段值 collect：最终操作，Collectors：数据转换 joining：连接符号
        String teacherNames = teachers.stream().map(Teacher::getName).collect(Collectors.joining(","));
        course.setTeacherNames(teacherNames);
        // 保存
        insert(course);
    }

    /*
     * @Description: 判断课程是否存在
     * @Author: Director
     * @Date: 2022/9/4 16:56
     * @param course: 课程对象
     * @return: void
     **/
    private void isCourseExisted(Course course) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name", course.getName());
        Course selectCourse = selectOne(wrapper);
        AssertUtil.isNull(selectCourse, GlobaEnums.COURSE_EXISTED_ERROR);
    }

    @Override
    public void onLineCourse(Long courseId) {
//             1.参数校验
        AssertUtil.isNotNull(courseId,GlobaEnums.PARAM_IS_NULL_ERROR);
//             2.业务校验
        Course course = selectById(courseId);
//               课程必须存在
        AssertUtil.isNotNull(course,GlobaEnums.COURSE_ISEXISTENCE_ERROR);
//               课程状态必须是下架状态
        boolean equals = course.getStatus().equals(Course.STATUS_OFFLINE);
        AssertUtil.isTrue(equals,GlobaEnums.COURSE_ISSATE_ERROR);
//             3.修改课程状态（上架）+ 填写上架时间
        course.setStatus(Course.STATUS_ONLINE);
        course.setStartTime(new Date());
        updateById(course);

        courseDoc courseDoc = new courseDoc();
        CourseType courseType = courseTypeService.selectById(course.getCourseTypeId());
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        BeanUtils.copyProperties(course,courseDoc);


        BeanUtils.copyProperties(courseSummary,courseDoc);
        BeanUtils.copyProperties(courseMarket,courseDoc);
        courseDoc.setChargeName(courseMarket.getCharge().intValue()==1?"免费":"收费");
        courseDoc.setCourseTypeName(courseType.getName());


        searchFeignService.savechcourse(courseDoc);
        AssertUtil.isTrue(JSONResult.success().isSuccess(), GlobaEnums.COURSE_ON_ERROR);

    }

    @Override
    public CourseInfoVo courseDetail(Long courseId) {
        AssertUtil.isNotNull(courseId,GlobaEnums.PARAM_IS_NULL_ERROR);
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,GlobaEnums.COURSE_ISEXISTENCE_ERROR);
        AssertUtil.isTrue(course.getStatus()==Course.STATUS_ONLINE,GlobaEnums.COURSE_OFF_ERROR);

        //根据courseid查询出跟详情相关得信息
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);

        //查询老师
        EntityWrapper<CourseTeacher> cts = new EntityWrapper<>();
        cts.eq("course_id",courseId);
        //查询出课程下面所有的老师
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(cts);
        List<Long> ids = courseTeachers.stream()
                .map(CourseTeacher::getTeacherId).collect(Collectors.toList());
        List<Teacher> teachers = teacherService.selectBatchIds(ids);

        //查询课程章节
        List<CourseChapter> courseChapters = iCourseChapterService.listByCourseId(courseId);
        Map<Long, CourseChapter> courseChapterMap = courseChapters
                .stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));

        //1.为media微服务编写controller接口查询课程下视频
        //2.编写api-media,暴露Frign接口
        //3.依赖api-media,使用Feign远程调用查询课程下的视频信息
        JSONResult jsonResult = mediaFeignService.queryMediaByCourseId(courseId);
        //通过feign接口查询课程下面得媒体视频 然后进行判断
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobaEnums.COURSE_NOTFINDMEDIA_ERROR);
        if(jsonResult.getData()!=null){//查询道德媒体信息不为空 我们才往下面走
            List<MediaFile> mediaFiles = JSON.parseArray(jsonResult.getData().toString(), MediaFile.class);
            for (MediaFile mediaFile : mediaFiles) {
                mediaFile.setFileUrl("");
                CourseChapter courseChapter = courseChapterMap.get(mediaFile.getCourseId());
                if(courseChapter!=null){
                    courseChapter.getMediaFiles().add(mediaFile);
                }
            }
        }

        return new CourseInfoVo(
                course,
                courseDetail,
                courseSummary,
                courseMarket,
                courseChapters,
                teachers
        );
    }

    @Override
    public String getForUser(Long mediaId) {
        AssertUtil.isNotNull(mediaId,GlobaEnums.PARAM_IS_NULL_ERROR);
        //通过feign查询媒体信息
        JSONResult jsonResult = mediaFeignService.get(mediaId);
        AssertUtil.isTrue(jsonResult.isSuccess(),GlobaEnums.COURSE_NOTFINDMEDIA_ERROR);
        AssertUtil.isNotNull(jsonResult.getData(),GlobaEnums.COURSE_MEDIAISNOTNULL_ERROR);
        MediaFile mediaFile = JSON.parseObject(jsonResult.getData().toString(), MediaFile.class);
        if(mediaFile.getFree()){
            //如果点击得是免费得课程就直接返回路径给他看
            return mediaFile.getFileUrl();
        }
        // 3.根据mediaFile中的courseId查询当前登录人是否购买了课程 t_course_user_learn
        Long loginId=3L;
        EntityWrapper<CourseUserLearn> wrapper = new EntityWrapper<>();
        wrapper.eq("login_id",loginId);
        wrapper.eq("course_id",mediaFile.getCourseId());
        //通过login——id和courseid查询登陆人得信息，是否买了响应得课程
        CourseUserLearn courseUserLearn = iCourseUserLearnService.selectOne(wrapper);
        //查不到买的课程就提醒用户让他龟儿买
        AssertUtil.isNotNull(courseUserLearn,GlobaEnums.COURSE_NOBUYCOURSE_ERROR);
        //如果过期了就提醒客户再买课程 购买了并且在客观看有效期，返回地址
        boolean before = new Date().before(courseUserLearn.getEndTime());
        AssertUtil.isTrue(before,GlobaEnums.COURSE_OUTTIME_ERROR);
        return mediaFile.getFileUrl();
    }
}
